﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace robotGUI
{
    public partial class JoyDisplay : UserControl
    {
        int _x = 0;
        public int X { get { return _x; } set { _x = value; Invalidate(); } }
        int _y = 0;
        public int Y { get { return _y; } set { _y = value; Invalidate(); } }
        int _deadBand = 0;
        public int DeadBand { get { return (int)(_deadBand / (float)Width * 511); } set { _deadBand = (int)(value / 511f * Width); Invalidate(); } }

        public int XMin = -255;
        public int XMax = 255;
        public int YMin = -255;
        public int YMax = 255;

        public JoyDisplay()
        {
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);
            InitializeComponent();
        }

        private void JoyDisplay_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Pen borderPen;
            Pen bandPen;
            Pen crossPen;
            Brush backBrush;
            Brush circleBrush;
            if (Enabled)
            {
                borderPen = new Pen(SystemColors.WindowFrame);
                bandPen = new Pen(SystemColors.ControlText);
                bandPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
                backBrush = new SolidBrush(BackColor);
            }
            else
            {
                borderPen = new Pen(SystemColors.ControlDark);
                bandPen = new Pen(SystemColors.ControlDark);
                bandPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
                backBrush = new SolidBrush(SystemColors.Control);
            }
            g.DrawRectangle(borderPen, new Rectangle(0, 0, this.Width - 1, this.Height - 1));
            g.FillRectangle(backBrush, new Rectangle(1, 1, this.Width - 2, this.Height - 2));
            //Cursor circle and cross
            float xRange = XMax - XMin;
            float yRange = YMax - YMin;
            int circleSize = _deadBand * 2;
            if (Enabled)
            {
                circleBrush = new SolidBrush(Color.Red);
                crossPen = new Pen(Color.Red);
                int x = (int)((_x - XMin) / xRange * (this.Width - 1)) - circleSize / 2;
                int y = (int)((_y - YMin) / yRange * (this.Height - 1)) - circleSize / 2;
                g.FillEllipse(circleBrush, x, y, circleSize, circleSize);
                x = (int)((_x - XMin) / xRange * (this.Width - 1));
                y = (int)((_y - YMin) / yRange * (this.Height - 1));
                g.DrawLine(crossPen, x, y - 5, x, y + 5);
                g.DrawLine(crossPen, x - 5, y, x + 5, y);
                circleBrush.Dispose();
                crossPen.Dispose();
            }
            //Deadband rectangle and text
            int xMid = (Width - 1) / 2;
            int yMid = (Height - 1) / 2;
            if (clicked || dragging)
            {
                g.DrawRectangle(bandPen, xMid - _deadBand, yMid - _deadBand, _deadBand * 2, _deadBand * 2);
                string s = "DeadBand = " + DeadBand.ToString();
                SizeF sz = g.MeasureString(s, Font);
                g.DrawString(s, Font, SystemBrushes.ControlText, this.Width - sz.Width, this.Height - sz.Height);
            }
            //Center cross
            g.DrawLine(borderPen, xMid, yMid - 5, xMid, yMid + 5);
            g.DrawLine(borderPen, xMid - 5, yMid, xMid + 5, yMid);

            borderPen.Dispose();
            bandPen.Dispose();
            backBrush.Dispose();
        }

        bool clicked = false;
        bool dragging = false;
        Point clickPos;
        private void JoyDisplay_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                clicked = true;
                clickPos = new Point(e.X, e.Y);
            }
            this.Invalidate();
        }

        public delegate void SetDeadbandEvent(Object sender, SetDeadbandEventArgs e);
        public event SetDeadbandEvent SetDeadband;
        public void OnSetDeadband(int DeadBand)
        {
            if (SetDeadband != null) SetDeadband(this, new SetDeadbandEventArgs(DeadBand));
        }

        private void JoyDisplay_MouseUp(object sender, MouseEventArgs e)
        {
            if (dragging) OnSetDeadband(DeadBand);
            dragging = false;
            clicked = false;
            this.Invalidate();
        }

        private void JoyDisplay_MouseMove(object sender, MouseEventArgs e)
        {
            if (clicked && !dragging) 
                if (Math.Abs(clickPos.X - e.X) > 1 || Math.Abs(clickPos.Y - e.Y) > 1)
                    dragging = true;
            if (dragging) calculateDeadband(e.X, e.Y);
        }

        private void calculateDeadband(int eX, int eY)
        {
            int x = eX - clickPos.X;
            int y = eY - clickPos.Y;
            if (eX < Width / 2) x = -x;
            if (eY < Height / 2) y = -y;
            //_deadBand = 0;
            //if (x > _deadBand) _deadBand = x;
            //if (y > _deadBand) _deadBand = y;
            _deadBand += x + y;
            if (_deadBand < 0) _deadBand = 0;
            if (_deadBand > Width / 2) _deadBand = Width / 2;
            if (_deadBand > Height / 2) _deadBand = Height / 2;
            clickPos = new Point(eX, eY);
            Invalidate();
        }

    }
    //Event Args for when user sets a new deadband
    public class SetDeadbandEventArgs : EventArgs
    {
        public int DeadBand;
        public SetDeadbandEventArgs(int DeadBand)
        {
            this.DeadBand = DeadBand;
        }
    }

}
